package com.kifas.controller;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.kifas.entity.TransactionJurnalUmumEntity;
import com.kifas.model.xml.BukuHutangPostingModel;
import com.kifas.model.xml.BukuPiutangPostingModel;
import com.kifas.model.xml.BukuVoucherPostingModel;
import com.kifas.model.xml.PersistStatus;
import com.kifas.model.xml.TransactionJurnalUmumModel;
import com.kifas.service.EntityServiceManager;

@Component
@Scope("prototype")
@Path("/TransactionJurnals")
public class TransactionJurnalController {

	private static Logger log = Logger.getLogger(TransactionJurnalController.class);

	@Context
	UriInfo uriInfo;

	@Autowired
	private EntityServiceManager entityManager;

	@POST
	@Path("BukuPiutang")
	@Produces(MediaType.APPLICATION_XML)
	@Consumes(MediaType.APPLICATION_XML)
	public PersistStatus insertPiutang(JAXBElement<BukuPiutangPostingModel> xml) {
		BukuPiutangPostingModel model = xml.getValue();
		TransactionJurnalUmumModel main = new TransactionJurnalUmumModel(null, model.getMain().getAkunMaster().getKodeAkun(), model.getMain().getTanggal(),
				model.getMain().getDeskripsi(), model.getMain().getNoFaktur(), model.getMain().getDebet(), model.getMain().getKredit(), model.getMain()
						.getKeterangan(), model.getMain().getPosting(), model.getMain().getCreatedBy(), model.getMain().getCreatedDate());
		TransactionJurnalUmumModel balance = new TransactionJurnalUmumModel(null, model.getBalance().getAkunMaster().getKodeAkun(), model.getBalance()
				.getTanggal(), model.getBalance().getDeskripsi(), model.getBalance().getNoFaktur(), model.getBalance().getDebet(), model.getBalance()
				.getKredit(), model.getBalance().getKeterangan(), model.getBalance().getPosting(), model.getBalance().getCreatedBy(), model.getBalance()
				.getCreatedDate());
		try {
			if (insert(main) && insert(balance)) entityManager.markBukuPiutangAsPost(model.getMain().getIdBukuPiutang());
		} catch (Exception e) {
			return new PersistStatus("TransactionJurnalUmumEntity", "failed", "can not persist transaction jurnal");
		}
		return new PersistStatus("TransactionJurnalUmumEntity", "success");
	}

	@POST
	@Path("BukuHutang")
	@Produces(MediaType.APPLICATION_XML)
	@Consumes(MediaType.APPLICATION_XML)
	public PersistStatus insertHutang(JAXBElement<BukuHutangPostingModel> xml) {
		BukuHutangPostingModel model = xml.getValue();
		TransactionJurnalUmumModel main = new TransactionJurnalUmumModel(null, model.getMain().getAkunMaster().getKodeAkun(), model.getMain().getTanggal(),
				model.getMain().getDeskripsi(), model.getMain().getNoFaktur(), model.getMain().getDebet(), model.getMain().getKredit(), model.getMain()
						.getKeterangan(), model.getMain().getPosting(), model.getMain().getCreatedBy(), model.getMain().getCreatedDate());
		TransactionJurnalUmumModel balance = new TransactionJurnalUmumModel(null, model.getBalance().getAkunMaster().getKodeAkun(), model.getBalance()
				.getTanggal(), model.getBalance().getDeskripsi(), model.getBalance().getNoFaktur(), model.getBalance().getDebet(), model.getBalance()
				.getKredit(), model.getBalance().getKeterangan(), model.getBalance().getPosting(), model.getBalance().getCreatedBy(), model.getBalance()
				.getCreatedDate());
		try {
			if (insert(main) && insert(balance)) entityManager.markBukuHutangAsPost(model.getMain().getIdBukuHutang());
		} catch (Exception e) {
			return new PersistStatus("TransactionJurnalUmumEntity", "failed", "can not persist transaction jurnal");
		}
		return new PersistStatus("TransactionJurnalUmumEntity", "success");
	}

	@POST
	@Path("BukuVoucher")
	@Produces(MediaType.APPLICATION_XML)
	@Consumes(MediaType.APPLICATION_XML)
	public PersistStatus insertVoucher(JAXBElement<BukuVoucherPostingModel> xml) {
		BukuVoucherPostingModel model = xml.getValue();
		TransactionJurnalUmumModel main = new TransactionJurnalUmumModel(null, model.getMain().getAkunMaster().getKodeAkun(), model.getMain().getTanggal(),
				model.getMain().getDeskripsi(), model.getMain().getNoRef(), model.getMain().getDebet(), model.getMain().getKredit(), model.getMain()
						.getKeterangan(), model.getMain().getPosting(), model.getMain().getCreatedBy(), model.getMain().getCreatedDate());
		TransactionJurnalUmumModel balance = new TransactionJurnalUmumModel(null, model.getBalance().getAkunMaster().getKodeAkun(), model.getBalance()
				.getTanggal(), model.getBalance().getDeskripsi(), model.getBalance().getNoRef(), model.getBalance().getDebet(), model.getBalance().getKredit(),
				model.getBalance().getKeterangan(), model.getBalance().getPosting(), model.getBalance().getCreatedBy(), model.getBalance().getCreatedDate());
		try {
			if (insert(main) && insert(balance)) entityManager.markBukuVoucherAsPost(model.getMain().getIdBukuVoucher());
		} catch (Exception e) {
			return new PersistStatus("TransactionJurnalUmumEntity", "failed", "can not persist transaction jurnal");
		}
		return new PersistStatus("TransactionJurnalUmumEntity", "success");
	}

	private boolean insert(TransactionJurnalUmumModel model) {
		TransactionJurnalUmumEntity transactionJurnal = new TransactionJurnalUmumEntity(null, model.getKodeAkun(), model.getTanggal(), model.getDeskripsi(),
				model.getNoRef(), model.getDebet(), model.getKredit(), model.getKeterangan(), model.getPosting(), model.getCreatedBy(), model.getCreatedDate());
		try {
			entityManager.persist(transactionJurnal);
		} catch (Exception e) {
			log.error("can not persist transaction jurnal", e);
			return false;
		}
		return true;
	}

	@GET
	@Produces(MediaType.TEXT_XML)
	public List<TransactionJurnalUmumModel> getTransactionJurnals(@QueryParam("start") String start, @QueryParam("end") String end) {
		SimpleDateFormat formatter = new SimpleDateFormat("ddMMyyyy");
		try {
			return transformList(entityManager.getTransactionJurnals(formatter.parse(start), formatter.parse(end)));
		} catch (Exception e) {
			log.error("cannot parse date, perhaps query param pattern is wrong");
			return new ArrayList<TransactionJurnalUmumModel>();
		}
	}

	@GET
	@Path("Sumarries")
	@Produces(MediaType.TEXT_XML)
	public List<TransactionJurnalUmumModel> getTransactionJurnalSumarries(@QueryParam("start") String start, @QueryParam("end") String end) {
		// Get Jurnal By Range Date , Group By kd akun , nilai rupiah nya di
		// jumlahin
		SimpleDateFormat formatter = new SimpleDateFormat("ddMMyyyy");
		List<TransactionJurnalUmumEntity> list = new ArrayList<TransactionJurnalUmumEntity>();
		Date startDate = null;
		Date endDate = null;
		String kdAkun = null;
		BigDecimal debet = new BigDecimal(0);
		BigDecimal kredit = new BigDecimal(0);
		int index = 0;
		try {
			startDate = formatter.parse(start);
			endDate = formatter.parse(end);
		} catch (Exception e) {
			log.error("cannot parse date, perhaps query param pattern is wrong");
			return new ArrayList<TransactionJurnalUmumModel>();
		}
		List<TransactionJurnalUmumEntity> transactionJurnals = entityManager.getTransactionJurnals(startDate, endDate);
		TransactionJurnalUmumEntity tmpJurnal = null;
		for (TransactionJurnalUmumEntity transactionJurnal : transactionJurnals) {
			if (kdAkun != null && !kdAkun.equals(transactionJurnal.getKodeAkun())) {
				index++;
				list.add(new TransactionJurnalUmumEntity(Long.valueOf(index), kdAkun, transactionJurnal.getTanggal(), transactionJurnal.getDeskripsi(),
						transactionJurnal.getNoRef(), debet, kredit, transactionJurnal.getKeterangan(), transactionJurnal.getPosting(), transactionJurnal
								.getCreatedBy(), transactionJurnal.getCreatedDate()));
				debet = new BigDecimal(0);
				kredit = new BigDecimal(0);
			}
			kdAkun = transactionJurnal.getKodeAkun();
			debet.add(transactionJurnal.getDebet());
			kredit.add(transactionJurnal.getKredit());
			tmpJurnal = transactionJurnal;
		}
		if (kdAkun != null && tmpJurnal != null) {
			index++;
			list.add(new TransactionJurnalUmumEntity(Long.valueOf(index), kdAkun, tmpJurnal.getTanggal(), tmpJurnal.getDeskripsi(), tmpJurnal.getNoRef(),
					debet, kredit, tmpJurnal.getKeterangan(), tmpJurnal.getPosting(), tmpJurnal.getCreatedBy(), tmpJurnal.getCreatedDate()));
		}
		return transformList(list);
	}

	private List<TransactionJurnalUmumModel> transformList(List<TransactionJurnalUmumEntity> transactionJurnals) {
		List<TransactionJurnalUmumModel> transactionJurnalModels = new ArrayList<TransactionJurnalUmumModel>();
		for (TransactionJurnalUmumEntity transactionJurnal : transactionJurnals) {
			transactionJurnalModels.add(transform(transactionJurnal));
		}
		return transactionJurnalModels;
	}

	private TransactionJurnalUmumModel transform(TransactionJurnalUmumEntity transactionJurnal) {
		return new TransactionJurnalUmumModel(transactionJurnal.getIdJurnal(), transactionJurnal.getKodeAkun(), transactionJurnal.getTanggal(),
				transactionJurnal.getDeskripsi(), transactionJurnal.getNoRef(), transactionJurnal.getDebet(), transactionJurnal.getKredit(),
				transactionJurnal.getKeterangan(), transactionJurnal.getPosting(), transactionJurnal.getCreatedBy(), transactionJurnal.getCreatedDate());
	}
}
